import sqlite3
import datetime
from utils.logger import logger

class Db_client():
    '''
    Класс для работы с базой данных
    '''
    def __init__(self):
        with sqlite3.connect("database.db") as db:
            logger.debug("Database open")
            self.db = db
            self.cursor = db.cursor()
            self.create_tables()
        logger.debug("Database initialize")

    def create_tables(self):
        '''
        Создание таблиц базы данных
        '''
        self.cursor.execute("""CREATE TABLE IF NOT EXISTS users(
            id INTEGER PRIMARY KEY,
            state TEXT,
            default_account_id INTEGER,
            last_bot_message_id INTEGER
        )""")
        self.cursor.execute("""CREATE TABLE IF NOT EXISTS accounts(
            id INTEGER PRIMARY KEY,
            user_id INTEGER,
            full_name TEXT,
            aliases TEXT,
            description TEXT,
            balance FLOAT NOT NULL,

            FOREIGN KEY (user_id) REFERENCES users (id)
                ON DELETE CASCADE ON UPDATE NO ACTION
        )""")
        self.cursor.execute("""CREATE TABLE IF NOT EXISTS transactions(
            id INTEGER PRIMARY KEY,
            account_id INTEGER NOT NULL,
            value INTEGER NOT NULL,
            description TEXT,
            date TEXT NOT NULL,

            FOREIGN KEY (account_id) REFERENCES accounts (id)
                ON DELETE CASCADE ON UPDATE NO ACTION
        )""")
        self.db.commit()
        logger.debug("Database create tables")
        
    def isUserExist(self, id):
        '''
        Проверяет, есть ли пользователь с заданным'id' в базе данных
        '''
        isExist = self.cursor.execute(f"SELECT EXISTS(SELECT 1 FROM users WHERE id={id})").fetchone()[0]
        logger.debug(f"user_id:{id} isExist:{isExist}")
        return isExist

    def get_state(self, id):
        '''
        Возвращает состояние 'state' пользователя с заданным'id'
        '''
        if self.isUserExist(id):
            state = self.cursor.execute(f"SELECT state FROM users WHERE id = {id}").fetchone()[0]
            logger.debug(f"user_id:{id} state:{state}")
            return state
        return None
    
    def get_user_accounts(self, id):
        '''
        Возвращает все счета пользователя с заданным 'id'
        '''
        accounts = self.cursor.execute(f"SELECT * FROM accounts WHERE user_id = {id}").fetchall()
        logger.debug(f"user_id:{id} accounts:{accounts}")
        return accounts
    
    def get_user_default_account_id(self, id):
        '''
        Возвращает 'id' счета по умолчанию для пользователя с заданным 'id'
        '''
        account_id = self.cursor.execute(f"SELECT default_account_id FROM users WHERE id = {id}").fetchone()[0]
        logger.debug(f"user_id:{id} account_id:{account_id}")
        return account_id
    
    def get_user_last_bot_message_id(self, id):
        '''
        Возвращает 'id' последнего сообщения отправленное ботом в чат пользователя
        '''
        if self.isUserExist(id):
            message_id = self.cursor.execute(f"SELECT last_bot_message_id FROM users WHERE id = {id}").fetchone()[0]
            logger.debug(f"user_id:{id} last_bot_message_id:{message_id}")
            return message_id
        logger.debug(f"user_id:{id} last_bot_message_id:None")
        return None
    
    def get_account_name(self, id):
        '''
        Возвращает ИМЯ счета по его 'id'
        '''
        name = self.cursor.execute(f"SELECT full_name FROM accounts WHERE id = {id}").fetchone()[0]
        logger.debug(f"account_id:{id} full_name:{name}")
        return name
    
    def get_account_aliases(self, id):
        aliases = self.cursor.execute(f"SELECT aliases FROM accounts WHERE id = {id}").fetchone()[0]
        logger.debug(f"account_id:{id} aliases:{aliases}")
        return aliases

    def get_account_balance(self, id):
        '''
        Возвращает БАЛАНС счета по его 'id'
        '''
        balance = self.cursor.execute(f"SELECT balance FROM accounts WHERE id = {id}").fetchone()[0]
        logger.debug(f"account_id:{id} balance:{balance}")
        return balance

    def get_account_id(self, id, full_name):
        '''
        Возвращает 'id' счета по его имени и 'id' владельца
        '''
        account_id = self.cursor.execute(f"SELECT id FROM accounts WHERE user_id = {id} AND full_name='{full_name}'").fetchone()[0]
        logger.debug(f"user_id:{id} account_name:{full_name} account_id{account_id}")
        return account_id

    def get_transaction_ids(self, id):
        '''
        Возвращает все 'id' транзакций по заданному 'id' счета
        '''
        transactions = self.cursor.execute(f"SELECT id FROM transactions WHERE account_id = {id}").fetchall()
        transaction_ids = []
        for transaction in transactions:
            transaction_ids.append(transaction[0])
        logger.debug(f"account_id:{id} transaction_ids:{transaction_ids}")
        return transaction_ids
    
    def get_transaction_value(self, id):
        '''
        Возвращает значение транзакции по его 'id'
        '''
        value = self.cursor.execute(f"SELECT value FROM transactions WHERE id = {id}").fetchone()[0]
        logger.debug(f"transaction_id:{id} value:{value}")
        return value
    
    def get_transaction_description(self, id):
        '''
        Возвращает описание транзакции по его 'id'
        '''
        description = self.cursor.execute(f"SELECT description FROM transactions WHERE id = {id}").fetchone()[0]
        logger.debug(f"transaction_id:{id} description:{description}")
        return description

    def set_state(self, id, state):
        '''
        Задает новое состояние 'state' пользователю по заданному 'id'
        '''
        self.cursor.execute(f"UPDATE users SET state='{state}' WHERE id={id}")
        self.db.commit()
        logger.debug(f"user_id:{id} state:{state}")
    
    def set_balance(self, id, balance):
        '''
        Задает новый баланс счету с заданным 'id'
        '''
        self.cursor.execute(f"UPDATE accounts SET balance={balance} WHERE id={id}")
        self.db.commit()
        logger.debug(f"account_id:{id} balance:{balance}")
    
    def set_last_bot_message_id(self, id, message_id):
        '''
        Задает 'id' последнего сообщения отправленный ботом пользователю с заданным 'id'
        '''
        self.cursor.execute(f"UPDATE users SET last_bot_message_id={message_id} WHERE id={id}")
        self.db.commit()
        logger.debug(f"user_id:{id} message_id:{message_id}")

    def set_default_account_id(self, id, account_id):
        '''
        Задает счет по умолчанию для пользователя с заданным 'id'
        '''
        self.cursor.execute(f"UPDATE users SET default_account_id={account_id} WHERE id={id}")
        self.db.commit()
        logger.debug(f"user_id:{id} account_id:{account_id}")
    
    def edit_account_full_name(self, id, full_name):
        '''
        Изменяет имя счета с заданным 'id'
        '''
        self.cursor.execute(f"UPDATE accounts SET full_name='{full_name}' WHERE id={id}")
        self.db.commit()
        logger.debug(f"account_id:{id} full_name:{full_name}")
    
    def edit_account_aliases(self, id, aliases):
        '''
        Изменяет имя счета с заданным 'id'
        '''
        self.cursor.execute(f"UPDATE accounts SET aliases='{aliases}' WHERE id={id}")
        self.db.commit()
        logger.debug(f"account_id:{id} aliases:{aliases}")
    
    def create_user(self, id):
        '''
        Создает нового пользователя в базе данных
        '''
        self.cursor.execute("INSERT INTO users(id,state) VALUES(?,?)", (id, None))
        self.db.commit()
        logger.debug(f"user_id:{id} True")

    def create_account(self, user_id, full_name, aliases=None, description=None, balance=0):
        '''
        Создает новый счет в accounts пользователю user_id
        '''
        self.cursor.execute("INSERT INTO accounts(user_id,full_name,aliases,description,balance) VALUES(?,?,?,?,?)", 
                    (user_id, full_name, aliases, description, balance))
        self.db.commit()
        logger.debug(f"user_id:{user_id} full_name:{full_name}")

    def create_transaction(self, account_id, value, description):
        '''
        Создает новую транзакцию в transactions счету account_id
        '''
        date = datetime.date.today()
        self.cursor.execute("INSERT INTO transactions(account_id,value,description,date) VALUES(?,?,?,?)", 
                    (account_id, value, description, date))
        self.db.commit()
        logger.debug(f"account:{account_id} value:{value} description:{description} date:{date}")
    
    def delete_account(self, id):
        '''
        Удаляет аккаунт у пользователя, заменяя владельца на Null
        '''
        self.cursor.execute(f"UPDATE accounts SET user_id=Null WHERE id={id}")
        self.db.commit()
        logger.debug(f"{id}")

db = Db_client()